# -*- coding:utf-8 -*-
from time import sleep

from qturboframe.lib.webdriver.remote.webdriver import WebDriver
from qturboframe.lib.utils.result import logger
from qturboframe.public_ui.h_ui.button import Button
from qturboframe.public_ui.h_ui.message import Message
from qturboframe.public_ui.h_ui.msg_box import MsgBox
from qturboframe.public_ui.h_ui.menu import Menu
from qturboframe.public_ui.h_ui.edit_grid import EditGrid
from qturboframe.public_ui.h_ui.transfer_table import TransferTable
from qturboframe.public_ui.h_ui.transfer import Transfer
from qturboframe.public_ui.h_ui.page import Page
from qturboframe.public_ui.h_ui.calendar import Calendar
from qturboframe.public_ui.h_ui.timer import Timer
from qturboframe.public_ui.h_ui.tree import Tree
from qturboframe.public_ui.h_ui.select_tree import SelectTree
from qturboframe.public_ui.h_ui.select import Select
from qturboframe.public_ui.h_ui.radio import Radio
from qturboframe.public_ui.h_ui.checkbox import Checkbox
from qturboframe.public_ui.h_ui.textarea import TextArea
from qturboframe.public_ui.h_ui.input_type import InputType
from qturboframe.public_ui.h_ui.input_number import InputNumber
from qturboframe.public_ui.h_ui.form import Form
from qturboframe.public_ui.h_ui.table import Table
from qturboframe.public_ui.h_ui.current_page import CurrentPage
from qturboframe.public_ui.h_ui.tabs import Tabs
from qturboframe.public_ui.h_ui.tag import Tag
from qturboframe.public_ui.h_ui.tree_grid import TreeGrid
from qturboframe.public_ui.h_ui.simple_table import SimpleTable
from qturboframe.public_ui.h_ui.type_field import TypeField
from qturboframe.public_ui.h_ui.ag_table import AgTable
from qturboframe.public_ui.h_ui.refactor_table import RefactorTable



class FrontEnd(object):
    '''
    class for HUI
    '''

    def __init__(self, driver:WebDriver, timeout=3):
        self.driver = driver
        self.timeout = timeout

    def wait_load(self, timeout=30):
        '''
        页面加载等待

        :Args:
         - timeout: 超时时间

        :Example:
         - 例: FrontEnd(driver).wait_load(10)
        '''
        timeout_active = 3
        timeout1 = 0
        if timeout > timeout_active:
            # 加载页面时load_div是激活状态
            while timeout1 < timeout_active * 10:
                loading_div = self.driver.find_element_by_attribute('class name', 'h-loading-bar', timeout=0.1)
                if loading_div.is_displayed():
                    logger.debug('等待页面数据加载')
                    timeout1 += 1
                    sleep(0.1)
                else:
                    break
        # 页面加载完成后load_div继续隐藏
        timeout2 = 0
        while timeout2 < (timeout - timeout1) * 10:
            loading_div = self.driver.find_element_by_attribute('class name', 'h-loading-bar', timeout=0.1)
            if not loading_div.is_displayed():
                break
            else:
                logger.debug('等待页面数据加载完成')
                timeout2 += 1
                sleep(0.1)

    def current_page(self, idname=None):
        '''
        获取hui的当前页对象

        :Args:
         - idname: 当前页的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            当前页对象

        :Example:
         - 例1: cur_page = FrontEnd(driver).current_page()
         - 例2: cur_page = FrontEnd(driver).current_page({By.CLASS_NAME:'app-main'})
        '''
        if idname:
            current_page = CurrentPage(idname, self.driver, self.timeout)
        else:
            current_page = CurrentPage({'css selector':'section.app-main'}, self.driver, self.timeout)
        return current_page

    def msg_box(self, idname=None, timeout=3):
        '''
        获取hui的弹出框对象

        :Args:
         - idname: 弹出框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            弹出框对象

        :Example:
         - 例1: popwindow = FrontEnd(driver).msg_box()
         - 例2: popwindow = FrontEnd(driver).msg_box({By.ID:'id'})
        '''
        msgbox = MsgBox(idname, self.driver, timeout)
        return msgbox

    def menu(self, idname=None):
        '''
        hui的菜单栏对象

        :Args:
         - idname: 菜单栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Return:
            返回Menu对象

        :Example:
         - 例1: menu = FrontEnd(driver).menu()
         - 例2: menu = FrontEnd(driver).menu({By.ID:'id'})
        '''
        if idname:
            menu = Menu(idname, self.driver, self.timeout)
        else:
            menu = Menu({'class name':'h-sidebar-menu'}, self.driver, self.timeout)
        return menu

    def button(self, text=None, idname=None, father=None, index=1):
        '''
        获取hui的按钮对象

        :Args:
         - text: 按钮文本
         - idname: 按钮的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: button的祖先级元素，可以给按钮查找限定范围，不需要在整个页面中查找

        :Notes:
            三个参数必须要有一个

        :Example:
         - 例1: button = FrontEnd(driver).button(text='提交',father=msg_box)
         - 例2: button = FrontEnd(driver).button(idname={By.ID:'id'})
        '''
        if not text and not idname and not father:
            raise AttributeError('缺少参数，该方法至少需要一个参数！')
        if father is None:
            father = self.driver
        if idname:
            button = Button(idname, father, self.timeout, index=index)
        else:
            button = Button({'css selector':'button.h-btn', 'text':text}, father, self.timeout)
        return button

    def table(self, idname=None, father=None, index=1):
        '''
        获取表格对象

        :Args:
         - idname: 表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 表格的祖先级元素，可以给表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回表格对象

        :Example:
         - 例1: table = FrontEnd(driver).table()
         - 例2: table = FrontEnd(driver).table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            table = Table(idname, father, self.timeout, index=index)
        else:
            table = Table({'css selector':'div.h-table-wrapper'}, father, self.timeout)
        return table

    def refactor_table(self, idname=None, father=None, index=1):
        '''
        获取表格对象

        :Args:
         - idname: 表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 表格的祖先级元素，可以给表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回表格对象

        :Example:
         - 例1: refactor_table = FrontEnd(driver).refactor_table()
         - 例2: refactor_table = FrontEnd(driver).refactor_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            table = RefactorTable(idname, father, self.timeout, index=index)
        else:
            table = RefactorTable({'css selector': 'div.h-table-wrapper table'}, father, self.timeout)
        return table

    def ag_table(self, idname=None, father=None, index=1):
        '''
        获取ag表格对象

        :Args:
         - idname: 表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 表格的祖先级元素，可以给表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回表格对象

        :Example:
         - 例1: ag_table = FrontEnd(driver).ag_table()
         - 例2: ag_table = FrontEnd(driver).ag_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            table = AgTable(idname, father, self.timeout, index=index)
        else:
            table = AgTable({'css selector': 'div.ag-table'}, father, self.timeout)
        return table

    def simple_table(self, idname=None, father=None):
        '''
        获取简单表格对象

        :Args:
         - idname: 表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 表格的祖先级元素，可以给表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回表格对象

        :Example:
         - 例1: simple_table = FrontEnd(driver).simple_table()
         - 例2: simple_table = FrontEnd(driver).simple_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            simple_table = SimpleTable(idname, father, self.timeout)
        else:
            simple_table = SimpleTable({'css selector':'div.h-table-wrapper'}, father, self.timeout)
        return simple_table

    def page(self, idname=None, father=None, timeout=3):
        '''
        获取表格分页栏对象

        :Args:
         - idname: 表格分页栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 表格分页栏的祖先级元素，可以给表格分页查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回表格分页栏对象

        :Example:
         - 例1: page = FrontEnd(driver).page()
         - 例2: page = FrontEnd(driver).page({By.XPATH:'./parent::div/ul'}, father=table.element)
        '''
        if father is None:
            father = self.driver
        if idname:
            page = Page(idname, father, self.timeout)
        else:
            page = Page({'css selector': 'ul.h-page'}, father, timeout)
        return page

    def form(self, idname=None, father=None, index=1):
        '''
        获取hui表单对象

        :Args:
         - idname: 表单的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 表单的祖先级元素，可以给表单查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的表单对象

        :Example:
         - 例1: form = FrontEnd(driver).form(father=msg_box)
         - 例2: form = FrontEnd(driver).form({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            form = Form(idname, father, self.timeout, index=index)
        else:
            form = Form({'css selector':'form.h-form'}, father, self.timeout)
        return form

    def input_type(self, idname=None, father=None):
        '''
        获取hui文本框对象，适用于密码框

        :Args:
         - idname: 文本框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 文本框的祖先级元素，可以给文本框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的文本框对象

        :Example:
         - 例1: input_type = FrontEnd(driver).input_type(father=form)
         - 例2: input_type = FrontEnd(driver).input_type({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            input_type = InputType(idname, father, self.timeout)
        else:
            input_type = InputType(
                {'css selector':'input.h-input'}, father, self.timeout)
        return input_type

    def input_number(self, idname=None, father=None):
        '''
        获取hui数字框对象，适用于密码框

        :Args:
         - idname: 数字框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 数字框的祖先级元素，可以给文本框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的数字框对象

        :Example:
         - 例1: input_number = FrontEnd(driver).input_number(father=form)
         - 例2: input_number = FrontEnd(driver).input_number({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            input_number = InputNumber(idname, father, self.timeout)
        else:
            input_number = InputNumber(
                {'css selector':'input.h-input-number-input'}, father, self.timeout)
        return input_number

    def type_field(self, idname=None, father=None):
        '''
        获取hui文本框对象，适用于密码框

        :Args:
         - idname: 文本框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 文本框的祖先级元素，可以给文本框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的文本框对象

        :Example:
         - 例1: type_field = FrontEnd(driver).type_field(father=form)
         - 例2: type_field = FrontEnd(driver).type_field({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            type_field = TypeField(idname, father, self.timeout)
        else:
            type_field = TypeField(
                {'css selector':'.h-typefield-left'}, father, self.timeout)
        return type_field

    def textarea(self, idname=None, father=None):
        '''
        获取hui多行文本框对象

        :Args:
         - idname: 多行文本框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 多行文本框的祖先级元素，可以给多行文本框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的多行文本框对象

        :Example:
         - 例1: textarea = FrontEnd(driver).textarea(father=form)
         - 例2: textarea = FrontEnd(driver).textarea({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            textarea = TextArea(idname, father, self.timeout)
        else:
            textarea = TextArea(
                {'css selector':'textarea.h-input'}, father, self.timeout)
        return textarea

    def radioes(self, idname=None, father=None):
        '''
        获取hui单选按钮组对象

        :Args:
         - idname: 单选按钮组的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 单选按钮组的祖先级元素，可以给单选按钮组查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的单选按钮组对象

        :Example:
         - 例1: radioes = FrontEnd(driver).radioes(father=form)
         - 例2: radioes = FrontEnd(driver).radioes({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            radioes = Radio(idname, father, self.timeout)
        else:
            radioes = Radio({'css selector': 'input.h-radio-input'}, father, self.timeout)
        return radioes

    def checkboxes(self, idname=None, father=None):
        '''
        获取hui复选框组对象

        :Args:
         - idname: 复选框组的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 复选框组的祖先级元素，可以给复选框组查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的复选框组对象

        :Example:
         - 例1: checkboxes = FrontEnd(driver).checkboxes(father=form)
         - 例2: checkboxes = FrontEnd(driver).checkboxes({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            checkboxes = Checkbox(idname, father, self.timeout)
        else:
            checkboxes = Checkbox({'css selector': 'input.h-checkbox-input'}, father, self.timeout)
        return checkboxes

    def select(self, idname=None, father=None):
        '''
        获取hui下拉框对象

        :Args:
         - idname: 下拉框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 下拉框的祖先级元素，可以给下拉框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的下拉框对象

        :Example:
         - 例1: select = FrontEnd(driver).select(father=form)
         - 例2: select = FrontEnd(driver).select({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            select = Select(idname, father, self.timeout)
        else:
            select = Select(
                {'css selector': 'div.h-select'}, father, self.timeout)
        return select

    def calendar(self, idname=None, father=None):
        '''
        获取hui日期框对象

        :Args:
         - idname: 日历框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 日历框的祖先级元素，可以给日历框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的日期框对象

        :Usage:
         - calendar = FrontEnd(driver).calendar(father=form)
         - calendar = FrontEnd(driver).calendar({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            calendar = Calendar(idname, father, self.timeout)
        else:
            calendar = Calendar(
                {'css selector': 'div.h-date-picker'}, father, self.timeout)
        return calendar

    def timer(self, idname=None, father=None):
        '''
        获取hui时间控件对象

        :Args:
         - idname: 时间控件的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 时间控件的祖先级元素，可以给时间控件查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的时间控件对象

        :Usage:
         - timer = FrontEnd(driver).timer(father=form)
         - timer = FrontEnd(driver).timer({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            timer = Timer(idname, father, self.timeout)
        else:
            timer = Timer(
                {'css selector': 'div.h-date-picker'}, father, self.timeout)
        return timer

    def select_tree(self, idname=None, father=None):
        '''
        获取hui下拉树形框对象

        :Args:
         - idname: 下拉树形控件的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 下拉树形框的祖先级元素，可以给下拉树形框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的下拉树形框对象

        :Example:
         - 例1: select_tree = FrontEnd(driver).select_tree(father=form)
         - 例2: select_tree = FrontEnd(driver).select_tree({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            select_tree = SelectTree(idname, father, self.timeout)
        else:
            select_tree = SelectTree(
                {'css selector': 'div.h-selectTree'}, father, self.timeout)
        return select_tree

    def tree(self, idname=None, father=None):
        '''
        获取hui树形控件对象

        :Args:
         - idname: 树形控件的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 树形控件的祖先级元素，可以给树形控件查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的树形控件对象

        :Example:
         - 例1: tree = FrontEnd(driver).tree(father=msg_box)
         - 例2: tree = FrontEnd(driver).tree({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            tree = Tree(idname, father, self.timeout)
        else:
            tree = Tree({'css selector': 'ul.h-tree'}, father, self.timeout)
        return tree

    def editgrid_table(self, idname=None, father=None):
        '''
        获取editgrid表格对象

        :Args:
         - idname: editgrid表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: editgrid表格的祖先级元素，可以给editgrid表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回editgrid表格对象

        :Example:
         - 例1: editgrid = FrontEnd(driver).editgrid_table(father=msg)
         - 例2: editgrid = FrontEnd(driver).editgrid_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            table = EditGrid(idname, father, self.timeout)
        else:
            table = EditGrid({'css selector': 'div.h-editgird-wrapper'}, father, self.timeout)
        return table

    def transfer(self, idname=None, father=None):
        '''
        获取穿梭框对象

        :Args:
         - idname: 穿梭框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 穿梭框的祖先级元素，可以给穿梭框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的穿梭框对象

        :Example:
         - 例1: transfer = FrontEnd(driver).transfer(father=form)
         - 例2: transfer = FrontEnd(driver).transfer({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            transfer = Transfer(idname, father, self.timeout)
        else:
            transfer = Transfer(
                {'css selector': 'div.h-transfer'}, father, self.timeout)
        return transfer

    def transfer_table(self, idname=None, father=None):
        '''
        获取穿梭表格对象

        :Args:
         - idname: 穿梭表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 穿梭表格的祖先级元素，可以给穿梭表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回穿梭表格对象

        :Example:
         - 例1: trans_table = FrontEnd(driver).transfer_table(father=msg)
         - 例2: trans_table = FrontEnd(driver).transfer_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            table = TransferTable(idname, father, self.timeout)
        else:
            table = TransferTable({'css selector': 'div.h-transfer-table'}, father, self.timeout)
        return table

    def tree_table(self, idname=None, father=None):
        '''
        获取hui树形表格对象

        :Args:
         - idname: 树形表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 树形表格的祖先级元素，可以给树形表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的树形表格对象

        :Example:
         - 例1: tree_table = FrontEnd(driver).tree_table(father=msg_box)
         - 例2: tree_table = FrontEnd(driver).tree_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            tree_table = TreeGrid(idname, father, self.timeout)
        else:
            tree_table = TreeGrid({'css selector': 'div.h-editgird-wrapper'}, father, self.timeout)
        return tree_table

    def message(self, idname=None, timeout=3):
        '''
        获取消息框对象

        :Args:
         - idname: 消息框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            hui的消息框对象

        :Example:
         - 例1: msg = FrontEnd(driver).message()
         - 例2: msg = FrontEnd(driver).message({By.ID:'id'})
        '''
        if idname:
            message = Message(idname, self.driver, timeout)
        else:
            message = Message({'css selector': 'div.h-message'}, self.driver, timeout)
        return message

    def tabs(self, idname=None, father=None):
        '''
        获取tabs对象

        :Args:
         - idname: tabs的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: tabs的祖先级元素，可以给tabs查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回tabs对象

        :Example:
         - 例1: tabs = FrontEnd(driver).tabs(father=msg_box)
         - 例2: tabs = FrontEnd(driver).tabs({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            tabs = Tabs(idname, father, self.timeout)
        else:
            tabs = Tabs({'css selector': 'div.h-tabs-nav-wrap div.h-tabs-nav'}, father, self.timeout)
        return tabs

    def tag(self, idname, father=None):
        '''
        获取tag对象

        :Args:
         - idname: tag的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: tag的祖先级元素，可以给tag查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回tag对象

        :Example:
         - 例1: tag = FrontEnd(driver).tag(father=msg_box)
         - 例2: tag = FrontEnd(driver).tag({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        return Tag(idname, father, self.timeout)